/*
 ***************************************************************************
 * MediaTeK Inc.
 * 4F, No. 2 Technology	5th	Rd.
 * Science-based Industrial	Park
 * Hsin-chu, Taiwan, R.O.C.
 *
 * (c) Copyright 2002-2012, MTK.
 *
 * All rights reserved.	MediaTeK's source	code is	an unpublished work	and	the
 * use of a	copyright notice does not imply	otherwise. This	source code
 * contains	confidential trade secret material of MediaTeK Tech. Any attemp
 * or participation	in deciphering,	decoding, reverse engineering or in	any
 * way altering	the	source code	is stricitly prohibited, unless	the	prior
 * written consent of MediaTeK, Inc. is obtained.
 ***************************************************************************

	Module Name:
	omci_upgrade_func.c

	Abstract:

	Revision History:
	Who			When			What
	--------	----------		----------------------------------------------
	Name		Date			Modification logs
	Xi.Wang		2020/8/26		Create
*/
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "omci.h"
#include "omci_me.h"
#include "omci_general_func.h"

typedef struct __pthreadArgImage{
                omciMeInst_t *imageInst[2];
                uint16_t instanceId;
                uint8_t currentImageState;
                uint32_t crc32_OLT;
}pthreadArgImage;

int tmrIdImage=0;
static uint8_t crcThreadExcuteFlag = 0;
static int crcthreadResult = -1;
int tmrIdSecMiss=0;
int sectionMiss = 0;
uint8_t gSectionNumber = 0;
short gTranCorrelatId = 0;
uint16_t downloadImageNum=0;
uint8_t windowSize=0;

downloadImage_t downloadImageBuffer = {
	 0, 0
};

int downSecNumInAWindow = 0;
int nextNewWindowFlag = 1;

uint8_t sectionBuffer_global[MAX_OMCI_UPGRADE_SECTION_NUM][OMCI_EXTENDED_MSG_CONT_LEN-1] = {0};
downloadSection_t swSection_global[MAX_OMCI_UPGRADE_SECTION_NUM] = {0};
downloadWindow_t swWindow_global = {0};

static int writeAttributeValueToOmciPayLoad(uint8_t* attributeValuePtr, uint8_t *responseContentPtr, uint16_t length)
{
	memcpy(responseContentPtr, attributeValuePtr, length);
	return 0;
}


/************************image operation function**************************/
OUT int omciAddSectionToWindow(uint8_t *data , uint8_t sectionNum, uint16_t sectionSize,uint16_t devId)
{	
	downloadSection_t *currentSectionPtr = NULL;
	downloadSection_t *preSectionPtr = NULL;

	if(data == NULL) {
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "%s [%d]: data is NULL\n",__FUNCTION__,__LINE__);
		return -1;
	}

	//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "%s [%d]: come into nomciAddSectionToWindow!\n",__FUNCTION__,__LINE__);

	if ((devId == OMCI_BASELINE_MSG && sectionSize >= OMCI_BASELINE_CONT_LEN)
		|| (devId == OMCI_EXTENED_MSG && sectionSize >= OMCI_EXTENDED_MSG_CONT_LEN))
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "%s [%d]: sectionSize is too large\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	swSection_global[sectionNum].nextSection = NULL;
	swSection_global[sectionNum].secNum = sectionNum;
	
	memcpy(sectionBuffer_global[sectionNum], data, sectionSize);
	swSection_global[sectionNum].secContent = sectionBuffer_global[sectionNum];
	swSection_global[sectionNum].secLength = sectionSize;

	//add to window list
	if(swWindow_global.sectionList_p== NULL){
		/*add section to head*/
		//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "%s [%d]: add section to head!\n",__FUNCTION__,__LINE__);
		swWindow_global.sectionList_p = &swSection_global[sectionNum];
	}else{		
		currentSectionPtr = swWindow_global.sectionList_p;
		if(currentSectionPtr->secNum > sectionNum)
		{
			/*add section to head*/
			//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "%s [%d]: inset section to head\n",__FUNCTION__,__LINE__);
			swSection_global[sectionNum].nextSection = currentSectionPtr;
			swWindow_global.sectionList_p = &swSection_global[sectionNum];
			goto retHandler;
		}
		
		while(currentSectionPtr->nextSection !=NULL){
			
			preSectionPtr = currentSectionPtr;
			currentSectionPtr = currentSectionPtr->nextSection;// find the next
			
			if((preSectionPtr->secNum < sectionNum)&&(currentSectionPtr->secNum > sectionNum))
			{
				/*add section to middle*/
				//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "%s [%d]: insert section to middle\n",__FUNCTION__,__LINE__);
				
				preSectionPtr->nextSection = &swSection_global[sectionNum];
				swSection_global[sectionNum].nextSection = currentSectionPtr;
				goto retHandler;
			}
		}
		/*add section to tail*/
		//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "%s [%d]: add section to tail!\n",__FUNCTION__,__LINE__);
		currentSectionPtr->nextSection = &swSection_global[sectionNum];
	}

retHandler:
	downloadImageBuffer.currentSize += sectionSize;
    return 0;
}

int omciCheckSwWindow(void){
	downloadSection_t *swSection_p=NULL;
	int i=0;
	
	swSection_p = swWindow_global.sectionList_p;
	if(swSection_p == NULL)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"%s [%d]: swSection_p == NULL\n",__FUNCTION__,__LINE__);
		return -1;
	}
	
	while(swSection_p != NULL)
	{
		if(swSection_p->secNum != i)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "%s [%d]: window error----section %d miss!!! secNumber in this window = %d\n",__FUNCTION__,__LINE__, i, downSecNumInAWindow);
			return -1;
		}
		swSection_p =  swSection_p->nextSection;
		i++;
	}

	return 0;
}
#if 0
static int freeSection(downloadSection_t *sectionList_p)
{
	downloadSection_t *nextSection_p=NULL;
	downloadSection_t *curSection_p = sectionList_p;
	
	if(curSection_p == NULL)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"freeSection: sectionList_p == NULL\n");
		return -1;
	}

	while(curSection_p != NULL)
	{
		nextSection_p = curSection_p->nextSection;
		if(NULL != curSection_p->secContent){
			free(curSection_p->secContent);
			curSection_p->secContent = NULL;
		}
		if(NULL != curSection_p){
			free(curSection_p);
			curSection_p = NULL;
		}
		curSection_p = nextSection_p;
	}

	return 0;
	
}

int freeAllWindow(downloadWindow_t *windowPtr)
{
	downloadWindow_t *nextWindow_p = NULL;
	downloadWindow_t *curWindow_p = windowPtr;

	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "enter freeAllWindow\r\n");

	if(curWindow_p == NULL){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "freeAllWindow: windowPtr == NULL\r\n");
		return -1;
	}	
	while(curWindow_p != NULL){
			nextWindow_p = curWindow_p->nextWindow;
			if(curWindow_p->sectionList_p != NULL)
			{
				freeSection(curWindow_p->sectionList_p);
				curWindow_p->sectionList_p = NULL;	
			}
			if(NULL != curWindow_p){
				free(curWindow_p);
				curWindow_p = NULL;
			}
			curWindow_p = nextWindow_p;
	}

	return 0;
	
}

int freeCurrentWindow(downloadWindow_t *curWindowPtr)
{
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "enter freeCurrentWindow\r\n");

	if(curWindowPtr == NULL){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "freeCurrentWindow: curWindowPtr == NULL\r\n");
		return -1;
	}	
	
	if(curWindowPtr->sectionList_p != NULL)
	{
		freeSection(curWindowPtr->sectionList_p);
		curWindowPtr->sectionList_p = NULL;	
	}

	free(curWindowPtr);

	return 0;
}
#endif
void reset_upgrade_global_resources(void)
{
	int i = 0;
	
	for(i = 0; i < MAX_OMCI_UPGRADE_SECTION_NUM; i++){
		memset(&sectionBuffer_global[i], 0, OMCI_EXTENDED_MSG_CONT_LEN);
		memset(&swSection_global[i], 0, sizeof(downloadSection_t));
	}
	memset(&swWindow_global, 0, sizeof(downloadWindow_t));
}

static int8_t saveSoftwareImageState(omciMeInst_t *image_0, omciMeInst_t *image_1){
	uint16_t length=0;
	uint8_t *attributeValuePtr=NULL;
	softimage_state_t softimage_state;

	if((image_0 == NULL) || (image_1 == NULL))
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE,"\r\ngetSoftwareImageState:---image not exesit!!");
		return -1;
	}
	/*set state by instance and tcapi */
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "saveSoftwareImageState: imageState =  %d\n",pSystemCap->currentImageState);

	switch(pSystemCap->currentImageState)
	{
		case SOFTWARE_IMAGE_STATE_S1_0:

			pSystemCap->softimage[0].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[0].active = ACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[1].active = INACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = INVALID_IMAGE;
			break;

		case SOFTWARE_IMAGE_STATE_S2_0:

			pSystemCap->softimage[0].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[0].active = ACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[1].active = INACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = INVALID_IMAGE;
			break;	

		case SOFTWARE_IMAGE_STATE_S3_0:

			pSystemCap->softimage[0].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[0].active = ACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[1].active = INACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;			

		case SOFTWARE_IMAGE_STATE_S4_0:

			pSystemCap->softimage[0].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[0].active = INACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[1].active = ACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;

		case SOFTWARE_IMAGE_STATE_S1_1:

			pSystemCap->softimage[0].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[0].active = INACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = INVALID_IMAGE;
			pSystemCap->softimage[1].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[1].active = ACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;

		case SOFTWARE_IMAGE_STATE_S2_1:

			pSystemCap->softimage[0].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[0].active = INACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = INVALID_IMAGE;
			pSystemCap->softimage[1].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[1].active = ACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;	

		case SOFTWARE_IMAGE_STATE_S3_1:

 			pSystemCap->softimage[0].committed = UNCOMMITTED_IMAGE;
 			pSystemCap->softimage[0].active = INACTIVE_IMAGE;
 			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[1].active = ACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;			

		case SOFTWARE_IMAGE_STATE_S4_1:
			
			pSystemCap->softimage[0].committed = UNCOMMITTED_IMAGE;
			pSystemCap->softimage[0].active = ACTIVE_IMAGE;
			pSystemCap->softimage[0].valid = VALID_IMAGE;
			pSystemCap->softimage[1].committed = COMMITTED_IMAGE;
			pSystemCap->softimage[1].active = INACTIVE_IMAGE;
			pSystemCap->softimage[1].valid = VALID_IMAGE;
			break;			
			
		default:
			return -1;
	}

#define COMMITTED_MASK	(1<<14)
#define ACTIVE_MASK		(1<<13)
#define VALID_MASK		(1<<12)
#define SET_SOFTIMAGE_ATTR(image, attriMask, attrVal)\
		do{\
			attributeValuePtr = omciGetInstAttriByMask(image, attriMask, &length);\
			if(NULL != attributeValuePtr){\
				*attributeValuePtr = attrVal;\
			}else{\
				omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE,"\r\ngetSoftwareImageState: attribute not exsit!!");\
			}\
		}while(0)

	//2--- Is committed
	SET_SOFTIMAGE_ATTR(image_0, COMMITTED_MASK, pSystemCap->softimage[0].committed);
	
	//3--- Is active
	SET_SOFTIMAGE_ATTR(image_0, ACTIVE_MASK, pSystemCap->softimage[0].active);
	
	//4--- Is valid
	SET_SOFTIMAGE_ATTR(image_0, VALID_MASK, pSystemCap->softimage[0].valid);
	
	//2--- Is committed
	SET_SOFTIMAGE_ATTR(image_1, COMMITTED_MASK, pSystemCap->softimage[1].committed);
	
	//3--- Is active
	SET_SOFTIMAGE_ATTR(image_1, ACTIVE_MASK, pSystemCap->softimage[1].active);
	
	//4--- Is valid
	SET_SOFTIMAGE_ATTR(image_1, VALID_MASK, pSystemCap->softimage[1].valid);

	memcpy(&softimage_state.image0, &pSystemCap->softimage[0], sizeof(softimage_state.image0));
	memcpy(&softimage_state.image1, &pSystemCap->softimage[1], sizeof(softimage_state.image1));
	omci_save_softimage_state(&softimage_state);
	return 0;
}


static int8_t softwareImageStateMachine(int action, uint16_t instanceId, uint8_t CRC_OK)
{
	uint8_t oldImageState=pSystemCap->currentImageState;
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "softwareImageStateMachine: action=%d,currentState=%d,instanceId=%d,CRC_OK=%d\n",
		action,pSystemCap->currentImageState,instanceId,CRC_OK);

	switch(pSystemCap->currentImageState)
	{
		case SOFTWARE_IMAGE_STATE_S1_0:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
						omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "softwareImageStateMachine: change currentState to  SOFTWARE_IMAGE_STATE_S2_0\n");
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_0,START_SW_DOWNLOAD, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					/*acive image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_0;
						return SOFTWARE_RESTART;
					}
					else
					{	
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_0,ACTIVE_SW, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					/*commit image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_0;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_0,COMMIT_SW, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}
					break;

				default:
					/*invalid action*/
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_0, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					return -1;
			}
			break;

		case SOFTWARE_IMAGE_STATE_S2_0:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, START_SW_DOWNLOAD, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					/*acive image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
						return SOFTWARE_RESTART;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, ACTIVE_SW, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					/*commit image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, COMMIT_SW, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_DOWNLOAD_SEC:
					/*donload image 1 sections*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, DOWNLOAD_SEC, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;	

				case MT_OMCI_MSG_TYPE_END_SW_DOWNLOAD:
					/*end download image 1*/
					if(instanceId == 1)
					{
						if(CRC_OK)	/*do CRC-32 check*/	
						{
							pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;
						}
						else
						{
							pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_0;
						}					
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, END_SW_DOWNLOAD, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
			
					break;
				case MT_OMCI_MSG_TYPE_SW_TIMEOUT:
					/*time out,back to s1_0*/
					if(instanceId == 0)
					{	
						/*time out,back to s1_1*/			
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_0;
					}
					else
					{
						/*time out,back to s3_1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;				

					}
					break;						
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_0, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;	

		case SOFTWARE_IMAGE_STATE_S3_0:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_0;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S3_0, START_SW_DOWNLOAD, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					if(instanceId == 0)
					{
						/*acive image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;
						return SOFTWARE_RESTART;
					}
					else
					{
						/*acive image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_0;
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					if(instanceId == 0)
					{
						/*commit image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;
					}
					else
					{
						/*commit image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_1;
					}	
					break;
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S3_0, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;

		case SOFTWARE_IMAGE_STATE_S4_0:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					if(instanceId == 0)
					{
						/*acive image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;
					}
					else
					{
						/*acive image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_0;
						return SOFTWARE_RESTART;						
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					if(instanceId == 0)
					{
						/*commit image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_0;
					}
					else
					{
						/*commit image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
					}	
					break;
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S4_0, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;

		case SOFTWARE_IMAGE_STATE_S4_1:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					if(instanceId == 0)
					{
						/*acive image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_1;
						return SOFTWARE_RESTART;												
					}
					else
					{
						/*acive image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					if(instanceId == 0)
					{
						/*commit image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_0;
					}
					else
					{
						/*commit image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_1;
					}	
					break;
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S4_1, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;

		case SOFTWARE_IMAGE_STATE_S3_1:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S3_1, START_SW_DOWNLOAD, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					if(instanceId == 1)
					{
						/*acive image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
						return SOFTWARE_RESTART;												
					}
					else
					{
						/*acive image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					if(instanceId == 1)
					{
						/*commit image 1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
					}
					else
					{
						/*commit image 0*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S4_0;
					}	
					break;
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S3_1, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;

		case SOFTWARE_IMAGE_STATE_S2_1:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, START_SW_DOWNLOAD, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					/*acive image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
						return SOFTWARE_RESTART;						
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, ACTIVE_SW, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					/*commit image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, COMMIT_SW, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;

				case MT_OMCI_MSG_TYPE_DOWNLOAD_SEC:
					/*donload image 0 sections*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, DOWNLOAD_SEC, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}						
					break;	

				case MT_OMCI_MSG_TYPE_END_SW_DOWNLOAD:
					/*end download image 0*/
					if(instanceId == 0)
					{
						if(CRC_OK)	/*do CRC-32 check*/	
						{
							pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
						}
						else
						{
							pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_1;
						}					
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, END_SW_DOWNLOAD, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
			
					break;
					
				case MT_OMCI_MSG_TYPE_SW_TIMEOUT:
					if(instanceId == 0)
					{	
						/*time out,back to s1_1*/			
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_1;
					}
					else
					{
						/*time out,back to s3_1*/
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S3_1;
					}
					break;						
					
				default:
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S2_1, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					/*invalid action*/
					return -1;
			}
			break;	

		case SOFTWARE_IMAGE_STATE_S1_1:
			switch(action)
			{
				case MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD:
					/*start download image 0*/
					if(instanceId == 0)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S2_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_1, START_SW_DOWNLOAD, instanceId=1\n",__FUNCTION__,__LINE__);				
						return -1;
					}
					break;

				case MT_OMCI_MSG_TYPE_ACTIVE_SW:
					/*acive image 10*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_1;
						return SOFTWARE_RESTART;						
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_1, ACTIVE_SW, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}					
					break;

				case MT_OMCI_MSG_TYPE_COMMIT_SW:
					/*commit image 1*/
					if(instanceId == 1)
					{
						pSystemCap->currentImageState = SOFTWARE_IMAGE_STATE_S1_1;
					}
					else
					{
						omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_1, COMMIT_SW, instanceId=0\n",__FUNCTION__,__LINE__);				
						return -1;
					}
					break;

				default:
					/*invalid action*/
					omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: STATE_S1_1, action=%d, instanceId=%d\n",__FUNCTION__,__LINE__,action,instanceId);									
					return -1;
			}
			break;
			
		default:

			break;
	}

	//if(oldImageState != pSystemCap->currentImageState)
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]: oldImageState=%d,currentImageState=%d,action=%d,instanceId=%d,CRC_OK=%d\n",
					__FUNCTION__,__LINE__,oldImageState,pSystemCap->currentImageState,action,instanceId,CRC_OK);
	
	return 0;
}


OUT int omciSwDownloadTimeout(downloadImage_t *dowloadImage ){
	omciManageEntity_t *currentME=NULL;
	omciMeInst_t *imageInst_0=NULL;
	omciMeInst_t *imageInst_1=NULL;
	if(tmrIdImage > 0)
	{
		timerStopS(tmrIdImage);
		tmrIdImage = 0;
	}
	if(tmrIdSecMiss > 0)
	{
		timerStopS(tmrIdSecMiss);
		tmrIdSecMiss = 0;
	}
	reset_upgrade_global_resources();

	dowloadImage->totalSize = 0;
	dowloadImage->currentSize = 0;
	currentME = omciGetMeByClassId(OMCI_CLASS_ID_SOFTWARE_IMGAE);
	if(currentME == NULL){
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: currentME==NULL, classId=%d\n",__FUNCTION__,__LINE__,OMCI_CLASS_ID_SOFTWARE_IMGAE);
		return -1;
	}
		
	imageInst_0 = omciGetInstanceByMeId(currentME, 0);
	imageInst_1 = omciGetInstanceByMeId(currentME, 1);
	softwareImageStateMachine(MT_OMCI_MSG_TYPE_SW_TIMEOUT, downloadImageNum, 1);		
	saveSoftwareImageState(imageInst_0, imageInst_1);

	return 0;
}

OUT int omciSwDownloadSecMissTimeout(omciGenericPayload_t * omciPayLoad ){
	uint8_t resultAndResean = 0;
	uint8_t devId = 0;
	uint32_t mic = 0;
	uint8_t *contentPtr = NULL;
	uint8_t *responseContentPtr = NULL;
	uint8_t secNum = 0;

	tmrIdSecMiss = 0;
	//sectionMiss = 0;
	omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "Enter omciSwDownloadSecMissTimeout!\n");
	devId = omciPayLoad->devId;
	contentPtr = omciPayLoad->msgContent;

	if(devId == OMCI_EXTENED_MSG)
	{
		mic = get32(contentPtr + omciPayLoad->msgContentLength);
		//imageDataLen = omciExtendedPayload->msgContentLength -1;
	}
	
	if (contentPtr == NULL)
	{
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"omciSwDownloadSecMissTimeout:---contentPtr is invalid!\n");									
		return OMCI_CMD_ERROR;/* result reason = ??*/
	}
	else
	{
		resultAndResean = OMCI_CMD_ERROR;
		
		secNum = (uint8_t)(*contentPtr);
		
		/*MessageType response AR = 0; AK =1*/
		responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));
	
		if(devId == OMCI_BASELINE_MSG)
		{	
		/*write resean and result*/
			responseContentPtr = contentPtr;
			memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
			
			writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr); 
		}	
		else
		{
		/*write resean and result*/
			responseContentPtr = contentPtr;
			memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4); 	
			writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);
	
		/*write response content length*/
			omciPayLoad->msgContentLength = 2;	
		
		/*write back 4 bytes mic*/
			put32(contentPtr+omciPayLoad->msgContentLength, mic);		
		}		
		/*write download section number*/
		responseContentPtr = contentPtr + 1;

		if (sectionMiss > 0) {
			omciPayLoad->tranCorrelatId = gTranCorrelatId;
			*responseContentPtr = gSectionNumber;
		}
		else
			*responseContentPtr = secNum;
		nextNewWindowFlag = 1;


		tmrIdSecMiss = 0;
		sectionMiss = 0;

		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciSwDownloadSecMissTimeout: omciDumpPkt!\n"); 		
		omciDumpPkt(omciPayLoad);
		omciPktSend(omciPayLoad, TRUE);
	}
	return 0;
}


void omciClearSwDownloadInfo(void)
{
	if(tmrIdImage > 0)
	{
		timerStopS(tmrIdImage);
		tmrIdImage = 0;
	}
	if(tmrIdSecMiss > 0)
	{
		timerStopS(tmrIdSecMiss);
		tmrIdSecMiss = 0;
	}
	
	reset_upgrade_global_resources();
	unlink(OMCI_UPLOAD_FW);
	downloadImageBuffer.totalSize = 0;
	downloadImageBuffer.currentSize = 0;
	downSecNumInAWindow = 0;
	nextNewWindowFlag = 1;
	return;
}


/*********************************************************************************************************************************
OMCI start download image action
MT	 					28
Type					Get current data 
Purpose					Get current counter value associated with one or more attributes of a performance monitoring managed entity
AK						Yes
Increment MIB data sync	No
**********************************************************************************************************************************/
int omciStartSwDownloadAction(uint16_t meClassId , omciMeInst_t *meInstant_ptr, omciGenericPayload_t * omciPayLoad, uint8_t msgSrc)
{
	uint8_t *contentPtr = NULL;
	uint8_t *responseContentPtr = NULL;
	
	omciManageEntity_ptr currentME;
	uint8_t resultAndResean = 0;
	int ret = 0;
	uint16_t instanceId=0;
	omciMeInst_t *imageInst_0=NULL;
	omciMeInst_t *imageInst_1=NULL;
	uint8_t MIBChangesFlag = 0;
	uint32_t imageSize = 0;
	uint8_t devId = 0;
	uint32_t mic = 0;
	extern uint8_t weWindowSize;

	devId = omciPayLoad->devId;
	contentPtr = omciPayLoad->msgContent;
	if(devId == OMCI_EXTENED_MSG)
	{
		mic = get32(contentPtr + omciPayLoad->msgContentLength);
	}
	omciClearSwDownloadInfo();

	if (contentPtr == NULL)
	{
		return  OMCI_CMD_ERROR; /* result reason = ??*/
	}
	else
	{
		instanceId = get16((uint8_t*)&(omciPayLoad->meId)+2);

		if(instanceId > 1)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciStartSwDownloadAction: Software image only two instance \n");
			return OMCI_CMD_ERROR;
		}

		windowSize = *contentPtr;
		imageSize = get32(contentPtr + 1);

		currentME = omciGetMeByClassId(meClassId);
		if(currentME == NULL){
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: currentME==NULL, classId=%d\n",__FUNCTION__,__LINE__,meClassId);
			return -1;
		}
		
		imageInst_0 = omciGetInstanceByMeId(currentME, 0);
		imageInst_1 = omciGetInstanceByMeId(currentME, 1);

		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciStartSwDownloadAction: oldImageState=%d\n",pSystemCap->currentImageState);

		ret = softwareImageStateMachine(MT_OMCI_MSG_TYPE_START_SW_DOWNLOAD, instanceId, 1);

		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciStartSwDownloadAction: newImageState=%d, ret=%d\n",pSystemCap->currentImageState,ret);
		
		if (ret == -1)
		{
			resultAndResean = OMCI_CMD_ERROR;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciStartSwDownloadAction: command processing error\n");
			
			goto pktSend;
		}
		else
		{

			saveSoftwareImageState(imageInst_0, imageInst_1);
			
			reset_upgrade_global_resources();
			
			downloadImageBuffer.totalSize = imageSize;
			downloadImageBuffer.currentSize = 0;
			
			/*we should start a timer for download software*/
			downloadImageNum = instanceId;	
			if(tmrIdImage > 0){
				timerStopS(tmrIdImage);
				tmrIdImage = 0;
			}
			tmrIdImage= timerStartS(1*TIMER_COUNT_MIN, (TimerCallback)omciSwDownloadTimeout , &downloadImageBuffer);
			if(tmrIdImage == -1)
			{
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciStartSwDownloadAction: timerStartS fail!\n");
				return -1;
			}

			resultAndResean =OMCI_CMD_SUCCESS;
			MIBChangesFlag = 1;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciStartSwDownloadAction: command processing success\n");
			
			goto pktSend;
			
		}
	}


pktSend:
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE,"omciSetAction:Enter pktSend 11\n");
	/* MIB data Sync operation*/
	if (MIBChangesFlag == 1)
	{
		omciDataSyncSeqIncret();
	}

	/*MessageType response AR = 0; AK =1*/
	responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));
	
	if(devId == OMCI_BASELINE_MSG)
	{	
	/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);	
	}
	else
	{
	/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4);
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);
		
	/*write response content length*/
		omciPayLoad->msgContentLength = 2;	
	/*write back 4 bytes mic*/
		put32(contentPtr+omciPayLoad->msgContentLength, mic);	
	}
	/*write window size*/
	responseContentPtr = contentPtr + 1;
	if (weWindowSize == 31) {
		if (windowSize < 32)
		writeAttributeValueToOmciPayLoad((uint8_t *)(&windowSize), responseContentPtr, sizeof(windowSize));
	else
		writeAttributeValueToOmciPayLoad((uint8_t *)(&weWindowSize), responseContentPtr, sizeof(weWindowSize));
	}
	else
		writeAttributeValueToOmciPayLoad((uint8_t *)(&weWindowSize), responseContentPtr, sizeof(weWindowSize));
	
	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciStartSwDownloadAction: omciDumpPkt!weWindowSize = %d\n", weWindowSize);			
	omciDumpPkt(omciPayLoad);	
	omciPktSend(omciPayLoad, TRUE);
	
	
	return 0;		
}

int omciDownloadSecAction(uint16_t meClassId , omciMeInst_t *meInstant_ptr, omciGenericPayload_t * omciPayLoad, uint8_t msgSrc)
{
	uint8_t *contentPtr = NULL;
	uint8_t *responseContentPtr = NULL;
	uint8_t resultAndResean = 0;
	int ret = 0;
	uint16_t instanceId=0;
	uint8_t secNum = 0;
	int reval=0;
	int remainSize=0;
	uint8_t devId = 0;
	uint16_t imageDataLen = 0;
	uint32_t mic = 0;
	uint8_t oldImageState=0;
	FILE *fp = NULL;
	downloadSection_t *swSectionPtr = NULL;
	
	devId = omciPayLoad->devId;
	contentPtr = omciPayLoad->msgContent;

	/*NOTE:  this functions will enter thusands time,  trace printf will cause ineffiency and even crash*/
	
	if(devId == OMCI_EXTENED_MSG)
	{
		mic = get32(contentPtr + omciPayLoad->msgContentLength);
		imageDataLen = omciPayLoad->msgContentLength -1;
	}else if(devId == OMCI_BASELINE_MSG)
	{
		imageDataLen = OMCI_BASELINE_CONT_LEN-1;
	}

	if (contentPtr == NULL)
	{
		return OMCI_CMD_ERROR;/* result reason = ??*/
	}
	else
	{
		instanceId = get16((uint8_t*)&(omciPayLoad->meId)+2);

		if(instanceId > 1)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciDownloadSecAction: Software image only two instance \n");
			return OMCI_CMD_ERROR;
		}

		secNum = (uint8_t)(*contentPtr);

		oldImageState = pSystemCap->currentImageState;
		ret = softwareImageStateMachine(MT_OMCI_MSG_TYPE_DOWNLOAD_SEC, instanceId, 1);

		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: oldImageState=%d, newImageState=%d, ret=%d, secNum=%d\n",
			oldImageState,pSystemCap->currentImageState,ret,secNum);
		
		if (ret == -1)
		{
			resultAndResean = OMCI_CMD_ERROR;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciDownloadSecAction: command processing error\n");
			return OMCI_CMD_ERROR;
		}
		else
		{
			if(nextNewWindowFlag == 1)
			{
				memset(&swWindow_global, 0, sizeof(downloadWindow_t));
				
				downSecNumInAWindow = 1;
				nextNewWindowFlag = 0;
			}
			else
			{
				downSecNumInAWindow++;
			}

			remainSize = downloadImageBuffer.totalSize - downloadImageBuffer.currentSize;
			if(remainSize >= imageDataLen)	
			{
				reval = omciAddSectionToWindow(contentPtr+1, secNum, imageDataLen, devId);
			}
			else
			{
				reval = omciAddSectionToWindow(contentPtr+1, secNum, remainSize, devId);
			}
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: reval=%d,remainSize=0x%x,imageDataLen=0x%x,currentSize=%#x\n", 
				reval,remainSize,imageDataLen,downloadImageBuffer.currentSize);
			if(reval == -1)
			{
				resultAndResean = OMCI_CMD_ERROR;
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciDownloadSecAction: command processing error\n");
				return OMCI_CMD_ERROR;
			}		

			if(tmrIdImage > 0)
			{
				timerStopS(tmrIdImage);
				tmrIdImage = 0;
			}
			tmrIdImage= timerStartS(1*TIMER_COUNT_MIN, (TimerCallback)omciSwDownloadTimeout , &downloadImageBuffer);
			if(tmrIdImage == -1)
			{
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciDownloadSecAction: timerStartS fail!\n");
				return -1;
			}
			
			if((omciPayLoad->msgType & DOWNLOAD_SEC_AR) == 0)	
			{
				if (sectionMiss == 0){
				//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: section download success, no response expected!\n");			
				return 0;
			}
			}
			else {
				gTranCorrelatId = omciPayLoad->tranCorrelatId;
				gSectionNumber = secNum;
			}
			//(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: window %d download success, response expected!windowsize = %d\n",downloadImageBuffer.currentWindowPtr->windowNum, downSecNumInAWindow);			

			if(tmrIdSecMiss > 0)
			{
				timerStopS(tmrIdSecMiss);
				tmrIdSecMiss = 0;
			}
			tmrIdSecMiss = timerStartS(20*TIMER_COUNT_S, (TimerCallback)omciSwDownloadSecMissTimeout , omciPayLoad);
			if(tmrIdSecMiss == -1)
				{
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciDownloadSecAction: Section miss timeout!\n");
				return -1;
				}
			if(omciCheckSwWindow() == -1)
			{
				sectionMiss = 1;
				omcidbgPrintf(OMCI_DEBUG_LEVEL_WARN, "omciDownloadSecAction: section miss!!\n");			
				return 0;
			}

			fp = fopen(OMCI_UPLOAD_FW, "a+");
		    if(fp == NULL)
		    {
		        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "open OMCI_UPLOAD_FW FILE fail!\n");
		        return OMCI_CMD_ERROR;
		    }
		    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "fopen OMCI_UPLOAD_FW FILE success!\n");
		    
	        swSectionPtr = swWindow_global.sectionList_p;
	        while(swSectionPtr != NULL)
	        {
	            fwrite(swSectionPtr->secContent, sizeof(uint8_t), swSectionPtr->secLength, fp);
	            swSectionPtr = swSectionPtr->nextSection;
	        }
		    fclose(fp);
		    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "fwrite OMCI_UPLOAD_FW FILE success!\n");
			
			resultAndResean =OMCI_CMD_SUCCESS;
			//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: command processing success\n");			
			goto pktSend;
		}
	}


pktSend:

	/*MessageType response AR = 0; AK =1*/
		responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));

	if(devId == OMCI_BASELINE_MSG)
	{	
	/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);	
	}
	else
	{
	/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4);		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);

	/*write response content length*/
		omciPayLoad->msgContentLength = 2;	
	
	/*write back 4 bytes mic*/
		put32(contentPtr+omciPayLoad->msgContentLength, mic);		
	}
	/*write download section number*/
	//printf( "omciDownloadSecAction: reason=%d,sectionMiss:%d!\n",resultAndResean,sectionMiss);
	responseContentPtr = contentPtr + 1;
	if ((resultAndResean == OMCI_CMD_SUCCESS) && (sectionMiss > 0)) {
		omciPayLoad->tranCorrelatId = gTranCorrelatId;
		*responseContentPtr = gSectionNumber;
	}
	else
	*responseContentPtr = secNum;

	
	//omcidbgPrintf(OMCI_DEBUG_LEVEL_NO_MSG, "omciDownloadSecAction:Id:%d,gID:%d,sec:%d,gSec:%d!\n",omciPayLoad->tranCorrelatId,gTranCorrelatId,
	//omciPayLoad->tranCorrelatId,*responseContentPtr,gSectionNumber);
	

	sectionMiss = 0;
	nextNewWindowFlag = 1;
	if(tmrIdSecMiss > 0)
	{
		timerStopS(tmrIdSecMiss);
		tmrIdSecMiss = 0;
	}

	//omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciDownloadSecAction: omciDumpPkt!\n");			
	//omciDumpPkt(omciPayLoad);
	omciPktSend(omciPayLoad, TRUE);
	
	return 0;		
}

static int startWriteImage(pthreadArgImage * pthreadArg)
{
    uint16_t instanceId=0;
    uint8_t currentImageState=0;
    char version[14] ={0};
    uint16_t firstAttrMask = 1<<15;  //the first attribute of SoftImage ME
    uint16_t len = 0;
    uint8_t *attributeValuePtr = NULL;
    
    if (pthreadArg == NULL)
        return -1;

    currentImageState = pthreadArg->currentImageState;
    instanceId = pthreadArg->instanceId;

    if ((0 != instanceId)&& (1 != instanceId))
        return -1;
    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "startWriteImage:pthreadArg->instanceId = %x\n", pthreadArg->instanceId);
    //to write image data to flash
    
    omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "startWriteImage:---write main image to flash!\n");
    omci_write_flash(instanceId,OMCI_UPLOAD_FW);
    
    //change machine state
    softwareImageStateMachine(MT_OMCI_MSG_TYPE_END_SW_DOWNLOAD, instanceId, 1);
    omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciEndSwDownloadAction: new currentImageState =  %d\n",currentImageState);

    omci_get_current_image_version(version,sizeof(version),OMCI_UPLOAD_FW);
    memcpy(pSystemCap->softimage[instanceId].version,version,sizeof(version));
    saveSoftwareImageState(pthreadArg->imageInst[0], pthreadArg->imageInst[1]);

    attributeValuePtr = omciGetInstAttriByMask(pthreadArg->imageInst[instanceId], firstAttrMask, &len);
    
    if(attributeValuePtr != NULL)
    {
        memcpy(attributeValuePtr, version, len);
    }
    
    return 0;
}

static void omciComputeCrcThread(void* arg){
    uint32_t crc32_ONU = 0;
    uint32_t crc32_OLT = 0;
    pthreadArgImage * pthreadArg = NULL;

    if(arg == NULL){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"[%s][%d] arg is a NULL pointer\n",__FUNCTION__,__LINE__);
        crcthreadResult = OMCI_CMD_ERROR;
        goto END;
    }

    /*Check CRC32*/
    pthreadArg = (pthreadArgImage*)arg;
    crc32_OLT = pthreadArg->crc32_OLT;
    crc32_ONU = compute_crc32_big_endian(OMCI_UPLOAD_FW);  
    if(crc32_ONU != crc32_OLT){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"[%s][%d] crc check Error!!! crc32_OLT=0x%x, crc32_ONU=0x%x\n",__FUNCTION__,__LINE__,crc32_OLT,crc32_ONU);
		unlink(OMCI_UPLOAD_FW);
        crcthreadResult = OMCI_CMD_ERROR;
        goto END;
    }

    downloadImageBuffer.totalSize = 0;
    downloadImageBuffer.currentSize = 0;
    if(0 != omci_is_current_image_valid(OMCI_UPLOAD_FW,crc32_OLT)){
        unlink(OMCI_UPLOAD_FW);
        crcthreadResult = OMCI_CMD_ERROR;
        goto END;
    }

    /*write image to flash*/
    if(0 == startWriteImage(pthreadArg)){
        crcthreadResult = OMCI_CMD_SUCCESS;
    }else{
        crcthreadResult = OMCI_CMD_ERROR;
    }
    unlink(OMCI_UPLOAD_FW);
    
END:
    if (pthreadArg != NULL){
        free(pthreadArg);
        pthreadArg = NULL;
    }
    return;
}

int omciEndSwDownloadAction(uint16_t meClassId , omciMeInst_t *meInstant_ptr, omciGenericPayload_t * omciPayLoad, uint8_t msgSrc)
{
    uint8_t *contentPtr = NULL;
    uint8_t *responseContentPtr = NULL;
    
    pthreadArgImage *pthreadArg = NULL;
    pthread_t thread_id;
    pthread_attr_t thread_attr;

    omciManageEntity_ptr currentME;
    uint8_t resultAndReason = 0;
    uint16_t instanceId=0;
    omciMeInst_t *imageInst_0=NULL;
    omciMeInst_t *imageInst_1=NULL;
    uint8_t MIBChangesFlag = 0;
    uint32_t crc32_OLT = 0;
    uint32_t imageSize = 0;
    uint8_t devId = 0;
	int ret = 0;

    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE,"[%s][%d]: come into omciEndSwDownloadAction!\n",__FUNCTION__,__LINE__);

    devId = omciPayLoad->devId;
    contentPtr = omciPayLoad->msgContent;
    
    if (contentPtr == NULL)
    {
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"[%s][%d]: content == NULL!\n",__FUNCTION__,__LINE__);
        resultAndReason = OMCI_CMD_ERROR;
        goto pktSend;
    }

    if(crcThreadExcuteFlag){
        switch(crcthreadResult){
            case OMCI_CMD_ERROR:
                crcthreadResult = -1;
                crcThreadExcuteFlag = 0;
                resultAndReason = OMCI_CMD_ERROR;
                omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: CRC32 Error or other reasons!\n",__FUNCTION__,__LINE__);
                break;
            case OMCI_CMD_SUCCESS:
                crcthreadResult = -1;
                crcThreadExcuteFlag = 0;
                MIBChangesFlag = 1;
                resultAndReason = OMCI_CMD_SUCCESS;
                omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]: CRC32 check and write image to flash successful!\n",__FUNCTION__,__LINE__);
                break;
            default:
                resultAndReason = OMCI_DEVICE_BUSY;
                omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]: Verifing CRC32 or writing image to flash, response device is busy!\n",__FUNCTION__,__LINE__);
                break;
        }
        goto pktSend;
    }
    
    instanceId = get16((uint8_t*)&(omciPayLoad->meId)+2);
    if(instanceId > 1)
    {
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: Software image only two instance \n",__FUNCTION__,__LINE__);
        resultAndReason = OMCI_UNKNOW_ME_INST;
        goto pktSend;
    }
    
    currentME = omciGetMeByClassId(meClassId);
    if(currentME == NULL){
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: currentME==NULL, classId=%d\n",__FUNCTION__,__LINE__,meClassId);
        resultAndReason = OMCI_UNKNOW_ME;
        goto pktSend;
    }
    
    imageInst_0 = omciGetInstanceByMeId(currentME, 0);
    imageInst_1 = omciGetInstanceByMeId(currentME, 1);

    crc32_OLT =get32(contentPtr);
    imageSize =get32(contentPtr+4); 
    omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "[%s][%d]: old currentImageState =%d, imageSize=%u",__FUNCTION__,__LINE__,pSystemCap->currentImageState,imageSize);
        
    if(imageSize != downloadImageBuffer.totalSize)
    {
        resultAndReason = OMCI_CMD_ERROR;
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: image size error! imageSize(%d) != downloadImageBuffer.totalSize(%d)\n",
            __FUNCTION__,__LINE__,imageSize,downloadImageBuffer.totalSize);             
        resultAndReason = OMCI_CMD_ERROR;
        goto pktSend;
    }

    if(tmrIdImage > 0)
    {
        timerStopS(tmrIdImage);
        tmrIdImage = 0;
    }
    
    pthreadArg = malloc(sizeof(pthreadArgImage));
    if(NULL == pthreadArg){
        resultAndReason = OMCI_CMD_ERROR;
        omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: pthreadArg malloc failure",__FUNCTION__, __LINE__);
        goto  pktSend;
    }
    memset(pthreadArg, 0, sizeof(pthreadArgImage));
    pthreadArg->currentImageState = pSystemCap->currentImageState;
    pthreadArg->imageInst[0] = imageInst_0;
    pthreadArg->imageInst[1] = imageInst_1;
    pthreadArg->instanceId = instanceId;
    pthreadArg->crc32_OLT = crc32_OLT;

    ret = pthread_attr_init(&thread_attr);
	if(ret != 0)
	{	
		free(pthreadArg);
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d] attribute creation fail!", __FUNCTION__, __LINE__);
		return -1;
	}
    ret = pthread_attr_setstacksize(&thread_attr, MAX_STACK_SIZE);
	if(ret != 0)	
	{			
		free(pthreadArg);		
		pthread_attr_destroy(&thread_attr);		
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d] attribute set stack size fail!", __FUNCTION__, __LINE__);		
		return -1;	
	}
    ret = pthread_attr_setdetachstate(&thread_attr,PTHREAD_CREATE_DETACHED); 
	if(ret != 0)
	{
		free(pthreadArg);
		omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]Set attribute fail!\n",__FUNCTION__, __LINE__);
		pthread_attr_destroy(&thread_attr);
		return -1;
		
	}
    
            
    if( pthread_create(&thread_id, &thread_attr, (void *)omciComputeCrcThread, (void*)pthreadArg) != 0 ){
        fprintf(stderr, "pthread_create error!!\n");
        resultAndReason = OMCI_CMD_ERROR;
        pthread_attr_destroy(&thread_attr);
        if (pthreadArg != NULL){
            free(pthreadArg);
            pthreadArg = NULL;
        }
        goto pktSend;
    }
    pthread_attr_destroy(&thread_attr);
    crcThreadExcuteFlag = 1;
    resultAndReason = OMCI_DEVICE_BUSY;

pktSend:
    if(resultAndReason != OMCI_DEVICE_BUSY){
		reset_upgrade_global_resources();
        downloadImageBuffer.totalSize = 0;
        downloadImageBuffer.currentSize = 0;
    }
    /* MIB data Sync operation*/
    if (MIBChangesFlag == 1)
    {
        omciDataSyncSeqIncret();
    }       
    
    /*MessageType response AR = 0; AK =1*/
    responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));

    if(devId == OMCI_BASELINE_MSG)
    {   
        /*write resean and result*/
        responseContentPtr = contentPtr;
        memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
        
        writeResultAndReasonToOmciPayLoad(resultAndReason, responseContentPtr); 

    }
    else
    {
        /*write resean and result*/
        responseContentPtr = contentPtr;
        memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4);     
        writeResultAndReasonToOmciPayLoad(resultAndReason, responseContentPtr);

        /*write response content length*/
        omciPayLoad->msgContentLength = 2;  
    }

    omciDumpPkt(omciPayLoad);
    omciPktSend(omciPayLoad, TRUE);
    
    return 0;

}

int omciActiveSwAction(uint16_t meClassId , omciMeInst_t *meInstant_ptr, omciGenericPayload_t * omciPayLoad, uint8_t msgSrc)
{
	uint8_t *contentPtr = NULL;
	uint8_t *responseContentPtr = NULL;
	
	omciManageEntity_ptr currentME;
	uint8_t resultAndResean = 0;
	int ret = 0;
	uint16_t instanceId=0;
	omciMeInst_t *imageInst_0=NULL;
	omciMeInst_t *imageInst_1=NULL;
	uint8_t MIBChangesFlag = 0;
	uint8_t devId = 0;
	uint32_t mic = 0;

	devId = omciPayLoad->devId;
	contentPtr = omciPayLoad->msgContent;

	if(devId == OMCI_EXTENED_MSG)
	{
		mic = get32(contentPtr + omciPayLoad->msgContentLength);
	}

	if (contentPtr == NULL)
	{
		return OMCI_CMD_ERROR; /* result reason = ??*/
	}
	else
	{
		instanceId = get16((uint8_t*)&(omciPayLoad->meId)+2);

		if(instanceId > 1)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR,"omciActiveSwAction: Software image only two instance \n");
			return OMCI_CMD_ERROR;
		}

		currentME = omciGetMeByClassId(meClassId);
		if(currentME == NULL){
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: currentME==NULL, classId=%d\n",__FUNCTION__,__LINE__,meClassId);
			return -1;
		}
		
		imageInst_0 = omciGetInstanceByMeId(currentME, 0);
		imageInst_1 = omciGetInstanceByMeId(currentME, 1);
		
		ret = softwareImageStateMachine(MT_OMCI_MSG_TYPE_ACTIVE_SW, instanceId, 1);
		
		if (ret == -1)
		{
			resultAndResean = OMCI_CMD_ERROR;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciActiveSwAction: softwareImageStateMachine error\n");
			return OMCI_CMD_ERROR;
		}
		else
		{
			ret = saveSoftwareImageState(imageInst_0,  imageInst_1);

			if(ret == -1)
			{
				resultAndResean = OMCI_CMD_ERROR;
				omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciActiveSwAction: saveSoftwareImageState error\n");
				return OMCI_CMD_ERROR;				
			}

			omci_set_bootflag(instanceId);
			
			resultAndResean =OMCI_CMD_SUCCESS;
			MIBChangesFlag = 1;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciActiveSwAction: command processing success\n");
			goto pktSend;			
		}
	}

pktSend:
/* MIB data Sync operation*/
	if (MIBChangesFlag == 1)
	{
		omciDataSyncSeqIncret();
	}	
	
/*MessageType response AR = 0; AK =1*/
	responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));

	if(devId == OMCI_BASELINE_MSG)
	{	
		/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);	

	}
	else
	{
		/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4);		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);

		/*write response content length*/
		omciPayLoad->msgContentLength = 1;	
		
		/*write back 4 bytes mic*/
		put32(contentPtr+omciPayLoad->msgContentLength, mic);	
	}

	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciActiveSwAction: omciDumpPkt!\n");			
	omciDumpPkt(omciPayLoad);
	omciPktSend(omciPayLoad, TRUE);
	
	sleep(2);

#if 1
	/*if(ret == SOFTWARE_RESTART) "software restart"
	**else "load and execute the image from flash"**/
	system("reboot");
#else	
	if(ret == SOFTWARE_RESTART)
	{
		/*software restart*/
		system("reboot");
	}
	else
	{
		/*load and execute the image from flash*/
		system("reboot");
	}
#endif
	return 0;		
}


int omciCommitSwAction(uint16_t meClassId , omciMeInst_t *meInstant_ptr, omciGenericPayload_t * omciPayLoad, uint8_t msgSrc)
{
	uint8_t *contentPtr = NULL;
	uint8_t *responseContentPtr = NULL;
	
	omciManageEntity_ptr currentME;
	uint8_t resultAndResean = 0;
	int ret = 0;
	uint16_t instanceId=0;
	omciMeInst_t *imageInst_0=NULL;
	omciMeInst_t *imageInst_1=NULL;
	uint8_t MIBChangesFlag = 0;	
	uint8_t devId = 0;
	uint32_t mic = 0;
	
	devId = omciPayLoad->devId;
	contentPtr = omciPayLoad->msgContent;
	if(devId == OMCI_EXTENED_MSG)
	{
		mic = get32(contentPtr + omciPayLoad->msgContentLength);
	}
	
	if (contentPtr == NULL)
	{
		return OMCI_CMD_ERROR; /* result reason = ??*/
	}
	else
	{
		instanceId = get16((uint8_t*)&(omciPayLoad->meId)+2);

		if(instanceId > 1)
		{
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciCommitSwAction: Software image only two instance \n");
			return OMCI_CMD_ERROR;
		}

		currentME = omciGetMeByClassId(meClassId);
		if(currentME == NULL){
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "[%s][%d]: currentME==NULL, classId=%d\n",__FUNCTION__,__LINE__,meClassId);
			return -1;
		}
		
		imageInst_0 = omciGetInstanceByMeId(currentME, 0);
		imageInst_1 = omciGetInstanceByMeId(currentME, 1);
		
		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciCommitSwAction: ---before--- currentImageState = %d\n",pSystemCap->currentImageState);
		
		ret = softwareImageStateMachine(MT_OMCI_MSG_TYPE_COMMIT_SW, instanceId, 1);
		omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "softwareImageStateMachine: ---after--- currentState = %d, ret=%d\n",pSystemCap->currentImageState,ret); 
		
		if (ret != 0)
		{
			resultAndResean = OMCI_CMD_ERROR;
			omcidbgPrintf(OMCI_DEBUG_LEVEL_ERROR, "omciCommitSwAction: command processing error\n");
			goto pktSend;
		}
		else
		{
			saveSoftwareImageState(imageInst_0,  imageInst_1);

			omci_set_bootflag(instanceId);
			
				/*add a flag into flash indicate that load/execute image 0*/;
			resultAndResean =OMCI_CMD_SUCCESS;
			MIBChangesFlag = 1;			
			omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciCommitSwAction: command processing success\n");
			goto pktSend;
			
		}
	}


pktSend:

/* MIB data Sync operation*/
	if (MIBChangesFlag == 1)
	{
		omciDataSyncSeqIncret();
	}
	
/*MessageType response AR = 0; AK =1*/
	responseMessageTypeHandle((uint8_t *)(&omciPayLoad->msgType));

	if(devId == OMCI_BASELINE_MSG)
	{	
		/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, OMCI_BASELINE_CONT_LEN);
		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);	

	}	
	else
	{
		/*write resean and result*/
		responseContentPtr = contentPtr;
		memset(responseContentPtr, 0, omciPayLoad->msgContentLength+4);		
		writeResultAndReasonToOmciPayLoad(resultAndResean, responseContentPtr);

		/*write response content length*/
		omciPayLoad->msgContentLength = 1;	
		
		/*write back 4 bytes mic*/
		put32(contentPtr+omciPayLoad->msgContentLength, mic);			
	}

	omcidbgPrintf(OMCI_DEBUG_LEVEL_TRACE, "omciCommitSwAction: omciDumpPkt!\n");			
	omciDumpPkt(omciPayLoad);
	
	omciPktSend(omciPayLoad, TRUE);
	return 0;		
}


